package com.smart.sso.server.log;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.smart.sso.server.common.LoginUser;
import com.smart.sso.server.model.Log;
import com.smart.sso.server.service.LogService;
import com.smart.sso.server.util.DateUtils;

/**
 * 切点类
 * @author CP
 *
 */
@Aspect
@Component
public class SystemLogAspect {
	//注入Service用于把日志保存数据库
	@Resource
	private LogService logService;
	
	//Controller层切点  
	/*
	 * @annotation表示拦截含有com.smart.sso.server.log.SystemControllerLog这个注解的方法
	 */
	@Pointcut("@annotation(com.smart.sso.server.log.SystemControllerLog)")
    public  void controllerAspect() {}
	
	 /** 
	   * 后置通知 用于拦截Controller层记录用户的操作 
	  * 
	  * @param joinPoint 切点 
	  */  
	 @After("controllerAspect()")  
	 public  void after(JoinPoint joinPoint) {
		 
		 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		 HttpSession session = request.getSession();
		//读取session中的用户
			LoginUser loginUser = (LoginUser)session.getAttribute("CURRENT_USER");
			if(loginUser == null)
				return;
			
			String ip = request.getRemoteAddr();
			
			try {
				Object[] res = getControllerMethodDescription(joinPoint);
				Log log = new Log();  
				log.setUserId(loginUser.getUserId());
	 //           log.setDescription(getControllerMethodDescription(joinPoint));  
//	            log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
//	            log.setType("0");  
	            log.setRequestIp(ip);  
//	            log.setExceptionCode( null);  
//	            log.setExceptionDetail( null);  
//	            log.setParams( null);  
	            log.setAccount(loginUser.getAccount());  
	            log.setOperationId((Integer)res[0]);
	            log.setDescription((String)res[1]);
	            log.setParameter((String)res[2]);
	            log.setOperationTime(new Date());  

	            //保存数据库  
	            logService.add(log);  
			}catch (Exception e) {
				// TODO: handle exception
			}
		}
		
//		@AfterThrowing(pointcut="serviceAspect()" , throwing = "e")
//		public void doAfterThrowing(JoinPoint joinPoint , Throwable e) {
//			HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
//			HttpSession session = request.getSession();
//			
//			LoginUser loginUser = (LoginUser)session.getAttribute("CURRENT_USER");
//			
//			String ip = request.getRemoteAddr();
//			String params = "";
//			if(joinPoint.getArgs() != null && joinPoint.getArgs().length>0) {
//				for(int i=0 ; i< joinPoint.getArgs().length ; i++) {
//					params += JSONUtils.toJSONString(joinPoint.getArgs()[i]) + ";";
//				}
//			}
//			
//			try {
//				Log log = new Log();  
//	            log.setDescription(getServiceMethodDescription(joinPoint));  
//	            log.setExceptionCode(e.getClass().getName());  
//	            log.setType("1");  
//	            log.setExceptionDetail(e.getMessage());  
//	            log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
//	            log.setParams(params);  
//	            log.setAccount(loginUser.getAccount());  
//	            log.setDate(DateUtils.getSysDate());  
//	            log.setRequestIp(ip);  
//	            //保存数据库  
//	            logService.add(log);  
//			}catch (Exception ex) {
//				// TODO: handle exception
//			}
//			
//			logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);
//		}
		
//		public static String getServiceMethodDescription(JoinPoint joinPoint) throws Exception {
//			String targetName = joinPoint.getTarget().getClass().getName();
//			String methodName = joinPoint.getSignature().getName();
//			Object[] arguments = joinPoint.getArgs();
//			Class targetClass = Class.forName(targetName);
//			Method[] methods = targetClass.getMethods();
//			
//			String description = "";
//			
//			for(Method method : methods) {
//				Class[] clazzs = method.getParameterTypes();
//				
//				if(clazzs.length == arguments.length) {
//					description = method.getAnnotation(SystemServiceLog.class).description();
//					break;
//				}
//			}
//			return description;
//		}
		
		public static Object[] getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
			String targetName = joinPoint.getTarget().getClass().getName();
			String methodName = joinPoint.getSignature().getName();
			Object[] arguments = joinPoint.getArgs();
			
			Class targetClass = Class.forName(targetName);
			Method[] methods = targetClass.getMethods();
			
			int operationId = -1;
			String description = "";
			Object theParameter = null;
			int paramNo = -1;
			
			for(Method method : methods) {
				if(method.getName().equals(methodName)) {
					Class[] clazzs = method.getParameterTypes();
					
					if(clazzs.length == arguments.length) {
						operationId = method.getAnnotation(SystemControllerLog.class).operationId();
						description = method.getAnnotation(SystemControllerLog.class).description();
						
						Annotation[][] paramAnnotations = method.getParameterAnnotations();
						if(paramAnnotations!=null && paramAnnotations.length>0) {
							for(int i=0 ; i < paramAnnotations.length ; i++ ) {
								Annotation[] paramAnnotation = paramAnnotations[i];
								for(Annotation annotation : paramAnnotation) {
									if(annotation instanceof SystemLogParam) {
										paramNo = i;
										break;
									}
								}
							}
						}
						break;
					}
				}
			}
			if(paramNo >= 0) {
				theParameter = arguments[paramNo];
			}
			Object[] res = new Object[3];
			res[0] = Integer.valueOf(operationId);
			res[1] = description;
			if(theParameter !=null)
				res[3] = theParameter;
			return res;
		}
	}
